package com.dq.utils;

import com.dq.exception.customException.AdminException;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;

/***
 * 时间工具类
 *
 */

public class TimeUtil {

    public static final String START_MONTH = "2018-10";

    private static final String FMT_0 = "yyyy-MM-dd";
    public static final String FMT_1 = "yyyy-MM-dd HH:mm:ss";
    private static final String FMT_2 = "yyyy-MM-dd HH:mm:ss.S";
    private static final String FMT_3 = "yyyy-MM";
    private static final String FMT_4 = "yyyyMMdd HHmmss";
    private static final String FMT_5 = "yyyyMMdd";
    public static final String FMT_6 = "yyyyMMddHHmmss";
    private static final String FMT_7 = "yyyy/MM/dd-HH:mm";
    private static final String FMT_8 = "yyyy-MM-dd HH:mm";
    private static final String FMT_9 = "yyyy/M/dd HH:mm";
    private static final String FMT_10 = "yyyy/MM/dd HH:mm";
    private static final String FMT_11 = "yyyy/M/dd H:mm";
    private static final String FMT_12 = "yyyy/MM/dd H:mm";
    private static final String FMT_13 = "yyyy/MM/d HH:mm";
    private static final String FMT_14 = "yyyy/MM/d H:mm";
    private static final String FMT_15 = "yyyy/M/d HH:mm";
    private static final String FMT_16 = "yyyy/M/d H:mm";
    private static final String FMT_17 = "HH:mm";
    private static final String FMT_18 = "MM/dd";

    public static final String YYYY_MM_DD = FMT_0;
    public static final String YYYY_MM_DD_HH_MM_SS = FMT_1;
    public static final String YYYY_MM = FMT_3;
    public static final String YYYYMMDD = FMT_5;
    public static final String YYYYMMDDHHMMSS = FMT_6;
    public static final String HHMM = FMT_17;
    public static final String MMDD = FMT_18;

    public static final long getTime(String str) throws AdminException {
        if (str.contains("/") && str.contains("-")) {
            if (FMT_7.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_7)).getMillis();
            }
        }
        if (str.contains("-")) {
            if (FMT_2.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_2)).getMillis();
            }
            if (FMT_1.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_1)).getMillis();
            }
            if (FMT_0.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_0)).getMillis();
            }
            if (FMT_3.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_3)).getMillis();
            }
            if (FMT_8.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_8)).getMillis();
            }
        }
        if (str.contains("/")) {
            if (FMT_9.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_9)).getMillis();
            }
            if (FMT_10.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_10)).getMillis();
            }
            if (FMT_11.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_11)).getMillis();
            }
            if (FMT_12.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_12)).getMillis();
            }
            if (FMT_13.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_13)).getMillis();
            }
            if (FMT_14.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_14)).getMillis();
            }
            if (FMT_15.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_15)).getMillis();
            }
            if (FMT_16.length() == str.length()) {
                return DateTime.parse(str, DateTimeFormat.forPattern(FMT_16)).getMillis();
            }
        }
        if (FMT_4.length() == str.length()) {
            return DateTime.parse(str, DateTimeFormat.forPattern(FMT_4)).getMillis();
        }
        if (FMT_5.length() == str.length()) {
            return DateTime.parse(str, DateTimeFormat.forPattern(FMT_5)).getMillis();
        }
        if (FMT_6.length() == str.length()) {
            return DateTime.parse(str, DateTimeFormat.forPattern(FMT_6)).getMillis();
        }


        throw new AdminException("时间格式化出错");
    }

    // 某月起始时间戳
    public static final long firstTimestampOfMonth(String month) {
        return timestamp(DateTime.parse(month).toString(FMT_3));
    }

    public static final long firstTimestampOfNextMonth(String month) {
        return firstTimestampOfMonth(monthAdd(month, 1));
    }

    public static final long firstTimestampOfLastMonth(String month) {
        return firstTimestampOfMonth(monthAdd(month, -1));
    }

    // 按月加减
    public static final String monthAdd(String var, int delta) {
        return monthAdd(DateTime.parse(var), delta);
    }


    public static final String monthAdd(DateTime var, int delta) {
        return var.plusMonths(delta).toString(FMT_3);
    }

    //按分钟加
    public static final Long minutesAddFMT_6(DateTime var, int delta) {
        return Long.valueOf(var.plusMinutes(delta).toString(FMT_6));
    }

    //按小时加
    public static final String hourAddFMT_6(DateTime var, int delta) {
        return var.plusHours(delta).toString(FMT_6);
    }

    //按日加
    public static final String dayAddFMT_6(DateTime var, int delta) {
        return var.plusDays(delta).toString(FMT_6);
    }

    // 获取月列表
    public static final List<String> monthLoop(String month0, String month1) { // 左闭右闭
        List<String> months = new ArrayList<>();
        long end = timestamp(month1);
        for (int i = 0; timestamp(monthAdd(month0, i)) <= end; i++) {
            months.add(monthAdd(month0, i));
        }
        return months;
    }

    // 某日起始时间戳
    public static final long firstTimestampOfDay(String day) {
        return timestamp(DateTime.parse(day).toString(FMT_0));
    }

    public static final long firstTimestampOfNextDay(String day) {
        return firstTimestampOfDay(dayAdd(day, 1));
    }

    public static final long firstTimestampOfLastDay(String day) {
        return firstTimestampOfDay(dayAdd(day, -1));
    }

    // 按日加减
    public static final String dayAdd(String var, int delta) {
        return dayAdd(DateTime.parse(var), delta);
    }

    // 按日加减
    private static final String dayAdd(DateTime var, int delta) {
        return var.plusDays(delta).toString(FMT_0);
    }

    //按年加减
    public static final String yearAdd(String var, int delta) {
        return yearAdd(DateTime.parse(var), delta);
    }

    private static final String yearAdd(DateTime var, int delta) {
        return var.plusYears(delta).toString(FMT_0);
    }

    // 获取月列表
    public static final List<String> dayLoop(String day0, String day1) { // 左闭右开
        List<String> r = new ArrayList<>();
        long end = timestamp(day1);
        for (int i = 0; timestamp(dayAdd(day0, i)) < end; i++) {
            r.add(dayAdd(day0, i));
        }
        return r;
    }

    // 获取时间戳
    public static final long timestamp(String var) {
        return timestamp(DateTime.parse(var));
    }

    // 获取时间戳
    public static final long timestamp(DateTime var) {
        return var.getMillis();
    }

    // 获取格式化时间
    public static final String getNowString(String fmt) {
        return getString(DateTime.now(), fmt);
    }

    // 获取格式化时间
    public static final String getString(DateTime var, String fmt) {
        return var.toString(fmt);
    }

    public static String getMonth(String flag) {
        return DateTime.parse(flag).toString(FMT_3);
    }

    public static List<String> getDaysOfMonth(String month) {
        long l0 = firstTimestampOfMonth(month), l1 = firstTimestampOfNextMonth(month);
        String d0 = new DateTime(l0).toString(YYYY_MM_DD), d1 = new DateTime(l1).toString(YYYY_MM_DD);
        return dayLoop(d0, d1);
    }

    public static Long formatFMT6Date(String dateTime) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(FMT_6);
        LocalDateTime ldt = LocalDateTime.parse(dateTime, dtf);
        long timestamp = ldt.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        return timestamp;
    }

    // 获取过去的几个月
    public static List<String> getPassedMonths(Integer page, Integer size) {
        if (null == page || page < 0) {
            page = 1;
        }
        if (null == size || size < 0) {
            size = 10;
        }
        page = page - 1;
        List<String> months = new ArrayList<>();
        DateTime now = DateTime.now();
        for (int i = page * size; i < page * size + size; i++) {
            String month = now.plusMonths(-i).toString(YYYY_MM);
            months.add(month);
            if (START_MONTH.equals(month)) {
                break;
            }
        }
        return months;
    }

    // 获取过去的几个月
    public static List<String> getPassedMonthsDesc(Integer page, Integer size) {
        if (null == page || page < 0) {
            page = 1;
        }
        if (null == size || size < 0) {
            size = 10;
        }
        page = page - 1;
        List<String> months = new ArrayList<>();
        DateTime now = DateTime.now();
        for (int i = page * size + size - 1; i >= 0; i--) {
            String month = now.plusMonths(-i).toString(YYYY_MM);
            months.add(month);
            if (START_MONTH.equals(month)) {
                break;
            }
        }
        return months;
    }

    public static List<String> getPassedDays(int n) {
        List<String> result = new ArrayList<>();
        DateTime now = DateTime.now();
        for (int i = 0; i < n; i++) {
            result.add(now.plusDays(-i).toString(YYYY_MM_DD));
        }
        return result;
    }

    public static List<String> getDistinctMonths(List<String> passedDays) {
        List<String> result = new ArrayList<>();
        for (String day : passedDays) {
            String month = DateTime.parse(day).toString(TimeUtil.YYYY_MM);
            if (!result.contains(month)) {
                result.add(month);
            }
        }
        return result;
    }

    public static String longToString(Long time, String temp) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(temp);
        return time == null ? null : simpleDateFormat.format(new Date(time));
    }

    public static String timeToString(Date time, String temp) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(temp);
        return time == null ? null : simpleDateFormat.format(time);
    }

    public static String dayHourMin(Long time) {
        if (time == null) {
            return "00天:00时:00分";
        }
        return time / (24 * 3600) + "天:" + (time / 3600 % 60) + "时:" + (time / 60 % 60) + "秒";
    }

    /**
     * 获取昨天这个时间的时间戳
     *
     * @return
     */
    public static Long getLastDayNowTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        Long dd = calendar.getTime().getTime();
        return dd;
    }

    /**
     * 获取某个月前当前时间
     *
     * @return
     */
    public static Long getLastMonthNowTimestamp(int n) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, n);
        Long dd = c.getTime().getTime();
        return dd;
    }

    /**
     * 获取某年前当前时间
     *
     * @param n
     * @return
     */
    public static Long getLastYearNowTimestamp(int n) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.YEAR, n);
        Long dd = c.getTime().getTime();
        return dd;
    }

    /**
     * 获取今天00点时间戳
     *
     * @return
     */
    public static Long getTodayZeroTimestamp() {
        Long time = System.currentTimeMillis();  //当前时间的时间戳
        long zero = time / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();
        return zero;
    }

    /**
     * 获取今天23.59.59时间戳
     *
     * @return
     */
    public static Long getTodayEndTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取昨天00点时间戳
     *
     * @return
     */
    public static Long getLastDayZeroTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 1, 0, 0, 0);
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取昨天23.59.59时间戳
     *
     * @return
     */
    public static Long getLastDayEndTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 1, 23, 59, 59);
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取7天前00点时间戳  不包含当天
     *
     * @return
     */
    public static Long getBeforeSevenDayZeroTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 7, 0, 0, 0);
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取30天前00点时间戳 不包含当天
     *
     * @return
     */
    public static Long getBeforeOneMonthZeroTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH) - 30, 0, 0, 0);
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取上个月第一天00点的时间戳
     *
     * @return
     */
    public static Long getLastMonthFirstDayZeroTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) - 1, 1, 0, 0, 0);
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取本月第一天00点时间戳
     *
     * @return
     */
    public static Long getThisMonthFirstDayZeroTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取上个月月底23.59.59时间戳
     *
     * @return
     */
    public static Long getLastMonthEndTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) - 1, calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取这个月月底23.59.59时间戳
     *
     * @return
     */
    public static Long getThisMonthEndTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        long tt = calendar.getTime().getTime();
        return tt;
    }

    /**
     * 获取这周周一00点时间
     *
     * @return
     */
    public static Long getThisWeekFirstTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return calendar.getTime().getTime();
    }

    /**
     * 获取上周周一00点时间
     *
     * @return
     */
    public static Long getLastWeekFirstTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.add(Calendar.DATE, -7);
        return calendar.getTime().getTime();
    }

    /**
     * 获取上周日23.59.59点时间
     *
     * @return
     */
    public static Long getThisWeekEndTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.add(Calendar.DATE, -1);
        return calendar.getTime().getTime();
    }


    /**
     * 获取当年的开始时间戳
     *
     * @param timeStamp 毫秒级时间戳
     * @param timeZone  如 GMT+8:00
     * @return
     */
    public static Long getYearStartTime(Long timeStamp, String timeZone) {
        Calendar calendar = Calendar.getInstance();// 获取当前日期
        calendar.setTimeZone(TimeZone.getTimeZone(timeZone));
        calendar.setTimeInMillis(timeStamp);
        calendar.add(Calendar.YEAR, 0);
        calendar.add(Calendar.DATE, 0);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取当年的最后时间戳
     *
     * @param timeStamp 毫秒级时间戳
     * @param timeZone  如 GMT+8:00
     * @return
     */
    public static Long getYearEndTime(Long timeStamp, String timeZone) {
        Calendar calendar = Calendar.getInstance();// 获取当前日期
        calendar.setTimeZone(TimeZone.getTimeZone(timeZone));
        calendar.setTimeInMillis(timeStamp);
        int year = calendar.get(Calendar.YEAR);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return calendar.getTimeInMillis();
    }


    // 计算两个时间差，返回为分钟。
    public static long CalTime(String time1, String time2) {
        DateFormat df = new SimpleDateFormat("HH:mm");
        long minutes = 0L;
        try {
            Date d1 = df.parse(time1);
            Date d2 = df.parse(time2);
            long diff = d1.getTime() - d2.getTime();// 这样得到的差值是微秒级别
            minutes = diff / (1000 * 60);
        } catch (ParseException e) {
            System.out.println("抱歉，时间日期解析出错。");
        }
        return minutes;
    }

    public static String addTime(String time) throws AdminException {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        Date date = null;
        try {
            date = df.parse(time);
            date.setTime(date.getTime() + 30 * 60 * 1000);
            System.out.println("当前时间      ：" + df.format(date));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return df.format(date);
    }

    public static List<String> getDayByMonth(int yearParam, int monthParam) {
        List list = new ArrayList();
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        aCalendar.set(yearParam, monthParam - 1, 1);
        int year = aCalendar.get(Calendar.YEAR);//年份
        int month = aCalendar.get(Calendar.MONTH) + 1;//月份
        int day = aCalendar.getActualMaximum(Calendar.DATE);
        for (int i = 1; i <= day; i++) {
            String aDate = null;
            if (month < 10 && i < 10) {
                aDate = String.valueOf(year) + "-0" + month + "-0" + i;
            }
            if (month < 10 && i >= 10) {
                aDate = String.valueOf(year) + "-0" + month + "-" + i;
            }
            if (month >= 10 && i < 10) {
                aDate = String.valueOf(year) + "-" + month + "-0" + i;
            }
            if (month >= 10 && i >= 10) {
                aDate = String.valueOf(year) + "-" + month + "-" + i;
            }

            list.add(aDate);
        }
        return list;
    }

    //获取某个日期的开始时间戳
    public static Long getDayStartTime(String d) {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = ft.parse(d);
            if (null != d) calendar.setTime(date);
            calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
            calendar.set(Calendar.MILLISECOND, 0);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return calendar.getTimeInMillis();
    }

    //获取某个日期的结束时间戳
    public static Long getDayEndTime(String d) {
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        try {
            Date date = ft.parse(d);
            if (null != d) calendar.setTime(date);
            calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
            calendar.set(Calendar.MILLISECOND, 999);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        return calendar.getTimeInMillis();
    }
}
